package grpc

import (
	"context"
	"gitlab.yctc.tech/zhiting/disk-manager.git/pkg/disk"
	"gitlab.yctc.tech/zhiting/disk-manager.git/pkg/lvm"
	"gitlab.yctc.tech/zhiting/disk-manager.git/pkg/proto"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

func wrapLvmError(err error) error {
	switch err {
	case lvm.ErrEmpty:
		fallthrough
	case lvm.ErrNotFound:
		return status.Error(codes.NotFound, err.Error())
	case lvm.ErrExists:
		return status.Error(codes.AlreadyExists, err.Error())
	}
	return err
}

func wrapVolumeGroupResp(ctx context.Context, vg *lvm.VolumeGroup) *proto.VolumeGroupResp {
	// 只读，可能为空
	pvs, _ := lvm.PVList(ctx)
	lvs, _ := lvm.LVList(ctx)
	rvg := wrapVG(vg, lvs, pvs)
	resp := proto.VolumeGroupResp{Data: rvg}
	return &resp
}

func wrapVG(vg *lvm.VolumeGroup, lvs map[string]*lvm.LogicalVolume, pvs map[string]*lvm.PhysicalVolume) *proto.VolumeGroup {
	rlvs := make([]*proto.LogicalVolume, 0)
	rpvs := make([]*proto.PhysicalVolume, 0)
	for _, lv := range lvs {
		if lv.VGName == vg.Name {
			rlvs = append(rlvs, wrapLV(lv))
		}
	}
	for _, pv := range pvs {
		if pv.VGName == vg.Name {
			rpvs = append(rpvs, wrapPV(pv))
		}
	}
	g := proto.VolumeGroup{
		Name:     vg.Name,
		Exported: vg.Exported,
		// size_unit: B
		Size:     vg.Size,
		FreeSize: vg.FreeSize,
		UUID:     vg.UUID,
		LVS:      rlvs,
		PVS:      rpvs,
	}
	return &g
}

func wrapPV(pv *lvm.PhysicalVolume) *proto.PhysicalVolume {
	p := proto.PhysicalVolume{
		Name:   pv.Name,
		VGName: pv.VGName,
		// size_unit: B
		Size:     pv.Size,
		UUID:     pv.UUID,
		MetaData: pv.MetaData,
	}
	if p.Size == 0 {
		size, _, _ := disk.GetPartitionSizes(pv.Name)
		p.Size = size
	}
	return &p
}

func wrapLV(lv *lvm.LogicalVolume) *proto.LogicalVolume {
	_, _, freeSize := disk.GetPartitionSizes(lv.Path)
	l := proto.LogicalVolume{
		Name:     lv.Name,
		VGName:   lv.VGName,
		Size:     lv.Size,
		FreeSize: freeSize,
		Path:     lv.Path,
		UUID:     lv.UUID,
	}
	return &l
}
